﻿using System;
using System.Collections.Generic;
using System.Linq;
using Gp.Scripts.Core;
using Gp.Scripts.Core.Skill;
using Gp.Scripts.Data.Skills;
using Gp.Scripts.GUI;
using Helpers;
using UnityEngine;

namespace Gp.Scripts.Core
{
    public enum AbilityState
    {
        /// <summary>
        /// 普通的攻击 移动能力
        /// </summary>
        CommonAbility,

        /// <summary>
        /// 技能
        /// </summary>
        SkillAbility,
    }

    public class AbilityUpdatedEvent
    {
        public List<SkillEntity> SkillEntities;
        public BaseUnit Unit;
        public AbilityState State;

        public AbilityUpdatedEvent(List<SkillEntity> skillEntities, BaseUnit unit, AbilityState state)
        {
            SkillEntities = skillEntities;
            Unit          = unit;
            State         = state;
        }
    }


    public class GameStateUnitSelect : GameStateWaitForInput
    {
        private List<SkillEntity> _abilities;
        public readonly BaseUnit CurrentUnit;
        public AbilityState State { get; private set; }
        private BattleIndicatorBase _indicator;

        public GameStateUnitSelect(BaseUnit unit)
        {
            CurrentUnit = unit;
            _abilities  = new List<SkillEntity>();
        }


        public override void OnEntitySelectEvent(BaseEntity entity, SelectEventType eventType)
        {
            base.OnEntitySelectEvent(entity, eventType);
            
            if (eventType != SelectEventType.SELECT || entity is not BaseUnit unit) return;

            if (unit.PlayerNumber == BattleSettle.CurrentPlayer.PlayerNumber) return;
            
            // 尝试执行攻击
            var disableReason = CurrentUnit.ComSkill.WeaponAttack.HumanExecute(new SkillContext {TargetUnit = unit, TargetCell = unit.GetCell()});
            if (!disableReason.Result(out var reasonId))
            {
                Global.Get<GUIManager>().Tips(reasonId.Text());
            }
        }

        public override void OnVCellSelectEvent(VBattleCell cell, SelectEventType eventType)
        {
            base.OnVCellSelectEvent(cell, eventType);
            if (eventType != SelectEventType.SELECT) return;

            var unit = BattleSettle.BattleCellGrid.GetUnitByCell(cell);
            if (unit != null)
            {
                this.OnEntitySelectEvent(unit, eventType);
                return;
            }

            // 尝试移动
            CurrentUnit.ComSkill.MoveSkill.HumanExecute(new SkillContext(){TargetCell = cell});
        }


        protected override void OnStateEnter(GameState lastState)
        {
            // 将相机移动至选中单位上
            UpdateAbility();

            // 发送单位选中事件
            CurrentUnit.TriggerEvent<Event_Unit.Select>();
            
            _indicator = BattleSettle.BattleUI3DNode.GetIndicator(CurrentUnit.ComSkill.MoveSkill.Config);
            _indicator.Display(new ShowIndicatorArgs(CurrentUnit){["GameState"] = this});
        }


        protected override void OnStateExit(GameState nextState)
        {
            CurrentUnit.TriggerEvent<Event_Unit.Deselect>();

            _abilities.ForEach(a => a.OnAbilityDeselected());
            _abilities.ForEach(a => a.CleanUp());
            _indicator?.CleanUp();
        }


        public void UpdateAbility(SkillEntity ability = null)
        {
            // 析构原有对象
            if (_abilities != null)
            {
                _abilities.ForEach(ab => ab.OnAbilityDeselected());
                _abilities.ForEach(ab => ab.CleanUp());
            }

            // 如果没有能力更新或集合为空，则将技能更新为攻击和移动
            if (ability == null)
            {
                _abilities = new List<SkillEntity>();
                var am = CurrentUnit.ComSkill;
                _abilities.Add(am.MoveSkill);
                _abilities.Add(am.WeaponAttack);
            }
            else
            {
                _abilities = new List<SkillEntity> {ability};
            }

            foreach (var a in _abilities)
            {
                if (a.UnitReference != CurrentUnit)
                    throw new Exception($"无法更改不同单位技能：{a.UnitReference.UnitName} 和 {CurrentUnit.UnitName} 是不同单位");
                a.OnAbilitySelected();
                a.Display();
            }


            MainArchitecture.Interface.SendEvent(new AbilityUpdatedEvent(_abilities, CurrentUnit, State));
        }
    }
}